package com.qiaofang.applet.service.property.service.impl;

import com.mongodb.client.result.DeleteResult;
import com.qiaofang.applet.common.base.MongoBaseService;
import com.qiaofang.applet.service.member.domain.Department;
import com.qiaofang.applet.service.member.domain.Employee;
import com.qiaofang.applet.service.member.repository.DepartmentRepository;
import com.qiaofang.applet.service.member.repository.EmployeeRepository;
import com.qiaofang.applet.service.other.domain.SignContact;
import com.qiaofang.applet.service.other.repository.SignContactRepository;
import com.qiaofang.applet.service.property.domain.*;
import com.qiaofang.applet.service.property.repository.*;
import com.qiaofang.applet.service.property.service.SyncDataQueueService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SyncDataQueueServiceImpl extends MongoBaseService<SyncDataQueue, String> implements SyncDataQueueService {

    private final SyncDataQueueRepository repository;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private EmployeeRepository employeeRepository;

    @Autowired
    private DistrictRepository districtRepository;

    @Autowired
    private AreaRepository areaRepository;

    @Autowired
    private EstateRepository estateRepository;

    @Autowired
    private EstatePhotoRepository estatePhotoRepository;

    @Autowired
    private PropertyVrRepository propertyVrRepository;

    @Autowired
    private PropertyVideoRepository propertyVideoRepository;

    @Autowired
    private PropertyContactRepository propertyContactRepository;

    @Autowired
    private PropertyRepository propertytRepository;

    @Autowired
    private FirsthandEstateRepository firsthandEstateRepository;

    @Autowired
    private SignContactRepository signContactRepository;


    @Autowired
    public SyncDataQueueServiceImpl(SyncDataQueueRepository repository) {
        super(repository);
        this.repository = repository;
    }

    @Override
    public Page<SyncDataQueue> findSyncDataQueuePage(String processingStatus, String dataType, int page, int size) {
        Pageable pageable = PageRequest.of((page - 1), size);
        return repository.findByProcessingStatusAndDataTypeOrderByUpdateTimeAsc(processingStatus, dataType, pageable);
    }

    @Override
    public int countByProcessingStatusAndDataType(String processingStatus, String dataType) {
        return repository.countByProcessingStatusAndDataType(processingStatus, dataType);
    }

    @Override
    public int deleteByProcessingStatusAndDataType(String processingStatus, String dataType) {
        return repository.deleteByProcessingStatusAndDataType(processingStatus,dataType);
    }

    @Override
    public void distinctAllSyncData() {
        distinctDepartment();
        distinctEmployee();
        distinctDistrict();
        distinctArea();
        distinctEstate();
        distinctEstatePhoto();
        distinctPropertyVr();
        distinctPropertyVideo();
        distinctPropertyContact();
        distinctProperty();
        distinctFirsthandEstate();
        distinctSignContact();

    }


    private void distinctDepartment() {
        List<Department> all = departmentRepository.findAll();
        if (CollectionUtils.isEmpty(all)){
            return;
        }
        List<Department> newList = all.stream().sorted(Comparator.comparing(Department::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (Department item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getDeptUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, Department.class);
        log.info("Department 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctEmployee() {
        List<Employee> all = employeeRepository.findAll();
        List<Employee> newList = all.stream().sorted(Comparator.comparing(Employee::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (Employee item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getEmployeeUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, Employee.class);
        log.info("Employee 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctDistrict() {
        List<District> all = districtRepository.findAll();
        List<District> newList = all.stream().sorted(Comparator.comparing(District::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (District item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getDistrictUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, District.class);
        log.info("District 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctArea() {
        List<Area> all = areaRepository.findAll();
        List<Area> newList = all.stream().sorted(Comparator.comparing(Area::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (Area item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getAreaUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, Area.class);
        log.info("Area 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctEstate() {
        List<Estate> all = estateRepository.findAll();
        List<Estate> newList = all.stream().sorted(Comparator.comparing(Estate::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (Estate item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getEstateUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, Estate.class);
        log.info("Estate 去除重复条数：", remove.getDeletedCount());
    }


    private void distinctEstatePhoto() {
        List<EstatePhoto> all = estatePhotoRepository.findAll();
        List<EstatePhoto> newList = all.stream().sorted(Comparator.comparing(EstatePhoto::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (EstatePhoto item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getEstateUuid() + item.getPhotoUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, EstatePhoto.class);
        log.info("EstatePhoto 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctPropertyVr() {
        List<PropertyVr> all = propertyVrRepository.findAll();
        List<PropertyVr> newList = all.stream().sorted(Comparator.comparing(PropertyVr::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (PropertyVr item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getPropertyUuid() + item.getVrId();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, PropertyVr.class);
        log.info("PropertyVr 去除重复条数：", remove.getDeletedCount());
    }


    private void distinctPropertyVideo() {
        List<PropertyVideo> all = propertyVideoRepository.findAll();
        List<PropertyVideo> newList = all.stream().sorted(Comparator.comparing(PropertyVideo::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (PropertyVideo item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getVideoUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, PropertyVideo.class);
        log.info("PropertyVideo 去除重复条数：", remove.getDeletedCount());
    }


    private void distinctPropertyContact() {
        List<PropertyContact> all = propertyContactRepository.findAll();
        List<PropertyContact> newList = all.stream().sorted(Comparator.comparing(PropertyContact::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (PropertyContact item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getPropertyUuid() + item.getContactId();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, PropertyContact.class);
        log.info("PropertyContact 去除重复条数：", remove.getDeletedCount());
    }


    private void distinctProperty() {
        List<Property> all = propertytRepository.findAll();
        List<Property> newList = all.stream().sorted(Comparator.comparing(Property::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (Property item : newList) {
            String uniqueUuid = item.getPropertyUniqueUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, Property.class);
        log.info("Property 去除重复条数：", remove.getDeletedCount());
    }


    private void distinctFirsthandEstate() {
        List<FirsthandEstate> all = firsthandEstateRepository.findAll();
        List<FirsthandEstate> newList = all.stream().sorted(Comparator.comparing(FirsthandEstate::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (FirsthandEstate item : newList) {
            String uniqueUuid = item.getEstateUniqueUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, FirsthandEstate.class);
        log.info("FirsthandEstate 去除重复条数：", remove.getDeletedCount());
    }

    private void distinctSignContact() {
        List<SignContact> all = signContactRepository.findAll();
        List<SignContact> newList = all.stream().sorted(Comparator.comparing(SignContact::getUpdateTime).reversed())
                .collect(Collectors.toList());
        Set<String> uuidSet = new HashSet<>();
        List<String> ids = new LinkedList<>();
        for (SignContact item : newList) {
            String uniqueUuid = item.getCompanyUuid() + item.getSignatoriesUuid();
            if (uuidSet.contains(uniqueUuid)){
                ids.add(item.getId());
            }else {
                uuidSet.add(uniqueUuid);
            }
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, SignContact.class);
        log.info("SignContact 去除重复条数：", remove.getDeletedCount());
    }
}
